package _case

import (
	"fmt"
	"time"
)

// 协程间通讯
func Commuication() {
	ch := make(chan int, 0) //定义一个可读可写的通道，0的意思是通道里只能有一个信息
	go commuicationF1(ch)   //向通道写数据
	go commuicationF2(ch)   //读取通道里的数据

}

// 接受一个只写通道
func commuicationF1(ch chan<- int) {
	// 通过循环向通道写入0-99
	for i := 0; i < 100; i++ {
		ch <- i
	}
}

// 从通道读数据
func commuicationF2(ch <-chan int) {
	for i := range ch {
		fmt.Println(i)
	}
}

// 并发场景下的同步机制
func ConcurrentSync() {
	//带缓存的通道 ，值在写入ch的时候是无序的
	ch := make(chan int, 10) //容量为10个缓存，最多写10个元素
	//向ch写入消息
	go func() {
		for i := 0; i <= 100; i++ {
			ch <- i
		}
	}()
	//写入消息
	go func() {
		for i := 0; i <= 100; i++ {
			ch <- i
		}
	}()
	//从ch 读取消息并打印
	go func() {
		for i := range ch { //顺序读取
			fmt.Println(i)
		}
	}()
}

// 通知协程退出，多路复用
func NoticeAndMultiplexing() {
	ch := make(chan int, 0)
	strCh := make(chan string, 0)
	done := make(chan struct{}, 0)
	go noticeAndMultiplexingF1(ch)
	go noticeAndMultiplexingF2(strCh)
	go noticeAndMultiplexingF3(ch, strCh, done)
	time.Sleep(5 * time.Second)
	close(done) //会去给所有的
}

func noticeAndMultiplexingF1(ch chan<- int) {
	for i := 0; i < 100; i++ {
		ch <- i
	}
}
func noticeAndMultiplexingF2(ch chan<- string) {
	for i := 0; i < 100; i++ {
		ch <- fmt.Sprintf("数字：%d", i)
	}
}

// 多路复用
func noticeAndMultiplexingF3(ch <-chan int, strCh <-chan string, done <-chan struct{}) {
	i := 0
	for {
		//select作为一个整体阻塞
		select { //select阻塞实现了多个channel的多路复用
		case i := <-ch:
			fmt.Println(i)
		case str := <-strCh:
			fmt.Println(str)
		case <-done:
			fmt.Println("收到消息，退出当前协程")
			return
			//加上default之后就会死循环
			//default:
			//	fmt.Println("执行default语句")
		}
		i++
		fmt.Println("累计执行次数", i)
	}
}
